package com.lanxum.common.task;

import com.alibaba.fastjson.JSONObject;
import com.itextpdf.text.pdf.BarcodePDF417;
import com.lanxum.common.constant.Constant;
import com.lanxum.common.entity.BarcodeParam;
import com.lanxum.common.utils.CommonUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.*;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.AttributedString;
import java.util.Iterator;
import java.util.concurrent.Callable;

/**
 * @author li.sun
 * @Description:
 * @date 2020/11/3 15:02
 */
public class BarcodeTask implements Callable {

    private static final Logger logger = LoggerFactory.getLogger(BarcodeTask.class);

    private BarcodeParam bp;

    public BarcodeTask(BarcodeParam bp) {
        this.bp = bp;
    }

    @Override
    public String call() throws Exception {
        // 生成二维码图片
        logger.info("新生成二维码图片－－－开始");
        String imageData = createBarcode(bp);
        if (StringUtils.isNotBlank(imageData)) {
            return imageData;
        } else {
            logger.info("新生成二维码图片---失败---,二维码文件名称:{}", bp.getImageName());
        }
        return null;
    }

    private static String createBarcode(BarcodeParam bp) {
        logger.info("生成条码图片，图片路径=" + bp.getImagePath());
        //获得二维码图片
        if (StringUtils.isBlank(bp.getDpi())) {
            bp.setDpi("600");
        }
        BufferedImage img = null;
        try {
            // 生成二维码图片
            img = createPdf417(bp);
            // 保存条码图片
            saveImage(img, bp);

            logger.info("二维码图片地址：{}，二维码图片名称：{}",  bp.getImagePath() , bp.getImageName());

            return bp.getImagePath() + bp.getImageName();
        } catch (Exception e) {
            logger.error("createBarcode生成条码图片异常－Exception:{}", e);
        }
        return null;
    }

    /**
     * 保存文件
     *
     * @param img
     * @throws IOException
     */
    private static void saveImage(BufferedImage img, BarcodeParam barcodeParam) throws IOException {
        OutputStream os = new BufferedOutputStream(new FileOutputStream(barcodeParam.getImagePath() + barcodeParam.getImageName()));

        byte[] a = process(img, Integer.parseInt(barcodeParam.getDpi()));
        os.write(a, 0, a.length);
        os.flush();
        os.close();

        //将文件保存到路径
        //ImageIO.write(img, suffix, os);
    }

    private static byte[] process(BufferedImage image, int dpi) throws IOException {
        for (Iterator<ImageWriter> iw = ImageIO.getImageWritersByFormatName("png"); iw.hasNext(); ) {
            ImageWriter writer = iw.next();
            ImageWriteParam writeParam = writer.getDefaultWriteParam();
            ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
            IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);
            if (metadata.isReadOnly() || !metadata.isStandardMetadataFormatSupported()) {
                continue;
            }
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            ImageOutputStream stream = null;
            try {
                // 设置图片DPI值
                setDPI(metadata, dpi);
                stream = ImageIO.createImageOutputStream(output);
                writer.setOutput(stream);
                writer.write(metadata, new IIOImage(image, null, metadata), writeParam);
            } finally {
                try {
                    stream.close();
                } catch (IOException e) {
                }
            }
            return output.toByteArray();
        }

        return null;
    }

    /**
     * 设置图片的DPI值
     *
     * @param metadata
     * @param dpi
     */
    private static void setDPI(IIOMetadata metadata, int dpi) throws IIOInvalidTreeException {
        double dotsPerMilli = 1.0 * dpi / 10 / Constant.INCH_2_CM;
        IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize");
        horiz.setAttribute("value", Double.toString(dotsPerMilli));

        IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize");
        vert.setAttribute("value", Double.toString(dotsPerMilli));

        IIOMetadataNode dim = new IIOMetadataNode("Dimension");
        dim.appendChild(horiz);
        dim.appendChild(vert);

        IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0");
        root.appendChild(dim);

        metadata.mergeTree("javax_imageio_1.0", root);
    }

    //使用对象传递属性生成带文字的二维码
    private static BufferedImage createPdf417(BarcodeParam bp) throws IOException {
        int txtX = 0;
        String fontFamily = bp.getTextFontFamily();
        int fontSize = bp.getTextFontSize();
        double size = bp.getScaling();
        int marginTop = bp.getTextMarginTop();
        // 二维码信息
        String imageContent = bp.getImageContent();
        // 二维码对应的中文
        String textContent = bp.getTextContent();
        BarcodePDF417 pdf = new BarcodePDF417();
        //容错等级4
        pdf.setErrorLevel(4);
        //固定列宽
        pdf.setOptions(BarcodePDF417.PDF417_FIXED_COLUMNS);
        //列宽数	//条码列宽数为cols+2，cols最小值为1
        pdf.setCodeColumns(bp.getColumns());
        //一个模块的宽高比例
//        pdf.setYHeight((int)size);
        pdf.setYHeight(1);
        // 二维码图片信息不为空时
        if (StringUtils.isNotBlank(imageContent)) {
            //二维码内容
            pdf.setText(imageContent.getBytes("utf-8"));
        }
        //获取生成二维码图片
        Image pdfImg = pdf.createAwtImage(Color.black, Color.white);
        //154
        int width = (int) (pdfImg.getWidth(null) * size);
        //34
        int height = (int) (pdfImg.getHeight(null) * size);

        //生成空白页，将空白图片的颜色设置白色
        BufferedImage img = new BufferedImage(width + 10, height + fontSize + 7, BufferedImage.TYPE_INT_RGB);
        for (int i = 0; i < img.getWidth(); i++) {
            for (int j = 0; j < img.getHeight(); j++) {
                img.setRGB(i, j, Constant.RGB_WHITE);
            }
        }
        Graphics2D g = (Graphics2D) img.getGraphics();

        // 二维码图片信息文字不为空,设备文字信息
        if (StringUtils.isNotBlank(textContent)) {
            Font font = new Font(fontFamily, Font.PLAIN, fontSize);
            g.setFont(font);
            //设置自体颜色
            g.setColor(Color.BLACK);
            AttributedString drawString = new AttributedString(textContent);
            drawString.addAttribute(TextAttribute.FONT, font, 0, textContent.length());
            int w = g.getFontMetrics().stringWidth(textContent);
            txtX = (width - w) / 2;
        }
        if (StringUtils.isNotBlank(textContent) && StringUtils.isNotBlank(imageContent)) {
            // 画图片
            g.drawImage(pdfImg, 5, 5, width, height, null);
            // 画文字
            g.drawString(textContent, txtX, height + marginTop + fontSize);
        } else if (StringUtils.isBlank(textContent) && StringUtils.isNotBlank(imageContent)) {
            // 画图片
            g.drawImage(pdfImg, 5, 5, width, height, null);
        } else if (StringUtils.isNotBlank(textContent) && StringUtils.isBlank(imageContent)) {
            // 画文字
            g.drawString(textContent, txtX, fontSize);
        }
        g.dispose();
        return img;
    }
}
